Hey there.
Welcome back.
Let's go ahead and continue to expand our knowledge of the Lua programming language.
This lecture is going to cover loops today a loop.
And programming is a block of code that is continually executed until a condition is met.
Some loops may execute for infinity, and others may execute for a set number of times.
In Lua there are three loops you'll want to note the for loop, the while loop, and the repeat loop.
The for loop is when you want to execute a block of code for an exact number of times.
However, we can also use a for loop using this function called Ipairs to loop through arrays or tables
that have index value pairs, and then we can also use the pairs function to loop through dictionaries
or tables that have key value pairs.
You can see one represents I for index and one amidst the I to represent key value pairs.
The next loop we're going to take a look at is the while loop.
And the while loop will continually execute a block of code until a specific condition is met.
Or we can have them execute for infinity.
And lastly is the repeat loop.
And the repeat loop also continually executes a block of code until a condition is met, or we can execute
them for infinity.
Now you might say, isn't that the exact same thing as a while loop?
Well, they are pretty similar, but there is one small difference that we're going to take a look at
in a moment.
Let's first go ahead and take a look at the for loop.
Now, as I said, the for loop is for when we want to execute a code, a set or finite number of times.
To create a for loop, we first type the for keyword, and afterwards we get to create a variable.
And this variable is going to help us keep track at what iteration we are in our for loop.
Most of the time we call this variable I, which stands for index, and we start at at a value typically
of one.
Next we're going to put a comma.
And after this we're going to put the value or the number of times we want this for loop to execute.
So for example maybe we want the for loop to execute ten times.
So I would put ten here.
And then we can put another comma.
And this represents the number that we should increment I by each time we loop.
So if I put one here that means I want to increment I by one each time through this loop.
And that means this loop will execute ten times.
However, if I put a number like two here, that means every single time through this loop I is going
to be incremented by two instead, which will cut down the number of times this loop is going to be
executed.
And we can also omit the last number completely and just have two numbers.
And that means by default our I will be incremented by one.
After we do this, we're going to put another keyword down.
And this is called the do keyword.
And what the do keyword does is it creates a new scope.
So if I hit enter, as you can see an n keyword appeared here because now we have a new scope that belongs
to this for loop.
Inside of this for loop I'm going to do is use our print function.
And I'm going to print out I or our index into the console.
So we can go ahead and go to our test tab and hit run.
And as you can see here inside of our console, I has been printed one two all the way down to ten.
So this for loop executed exactly ten times.
And you can also see how fast this for loop executed.
Because each time we get to see the milliseconds here, it took it one millisecond to execute it ten
times.
So it's almost instantaneous right.
For loops are extremely quick.
Now if I decided to put that third value in there and instead increment I by two each time, and then
we hit run and we go ahead and look at the output.
As you can see we started with an index of one.
We added two to our one and we got three.
And we keep adding two each time.
And that means our for loop only executed half as many times or five instead of ten.
And this is because once I has exceeded the value of ten, it's no longer going to execute.
It basically checks for that condition and then it breaks out of our for loop.
The next for loop, we can go ahead and take a look at is the for I pairs loop.
And again as I said this is for looping through arrays.
So what I'm going to do is I'm going to create a variable.
We can call it example array.
And we're going to create a new table here.
And inside of this table we can just insert a bunch of random numbers like 32.
We can put in 95 -1,043.4 50 -12.
Right.
So here we have an array with a bunch of different values inside of it.
And what we're going to do is put our for keyword down again.
But this time we're going to need to create two variables instead of one.
And this is because we need one variable to store the index.
And we need another variable to store the value at that index.
So typically most developers name the first variable I.
And then we put a comma afterwards.
And then the second variable we typically call it v to represent value.
Afterwards we have to use another keyword in Lua and this is called n and after this we need to pass
a function that's going to act as the iterator.
And an iterating function is simply one that is going to loop through all of the values in our table
and return them back to these variables.
And that is going to be the I pairs function.
So as you can see right here, it turns an iterator function and the table for use in a loop.
So we're going to use the I pairs function.
And we get to pass our table here.
So we'll pass example array.
And then afterward we need to put another do keyword to create a new scope.
And now what we could go ahead and do is print out the index and the value through each iteration of
this loop.
So I'm going to put a string here and I'm just going to say index.
And then we concatenate this with I.
And then we'll concatenate it with another string.
And this time we're going to say value put another colon.
And then we can concatenate this with v.
So now this should loop through every single index value pair inside of our array.
So through the first iteration we should get I of one and an I of one.
We should get the value of 32.
At the index of two we'll get 95 and so on.
So let's go ahead and hit run.
As you can see, here we go.
We get index one and our index one.
And we have the value of 32.
At index two we have the value of 95 and so on and so forth.
And as you can see it executes through our array chronologically.
It starts at one and continues going through our array in order.
Right.
Because arrays have an order to them.
They're organized.
However, we know that dictionaries on the other hand, are not organized.
And that's where the for pairs loop comes into play.
So we're going to go through the exact same process as we did up here.
I'm going to create a new variable I'll just call it example dictionary.
And inside of here, we're just going to make some random key value pairs.
I can call this first key something like data one and set it equal to 50.
I'll create another one.
Data two set it equal to 100.
Data three.
We can set to like 150 and then data four we can set to 200.
So here we have our dictionary with our keys and our values.
And what we need to do next is put our four keyword down.
And the only difference I'm going to do here is instead of naming the first variable I, I'm instead
going to name it K to let myself know that, hey, we're going to be looping through a dictionary that
has key value pairs.
So we have k and v key and value.
And then we put our in keyword again.
And this time we're going to be using the pairs function.
And we can go ahead and pass our dictionary here.
Put our do keyword down again and hit enter to create a new scope.
And now what I'm going to do here is use our print function again.
And this time I want to print out the keys so we can concatenate this with K and then concatenate that
with another string.
I'll just say value.
Put a colon here and then concatenate that with v.
So now we should loop through all of the different key value pairs in this table.
And it's going to be printed out into our console.
However what you're going to see is it's not going to print them in order.
We might print data to first or we might print data for first.
It's not going to be an order.
And that's because dictionaries do not have an order to them.
They're not like arrays.
So if we go ahead and hit run here.
As you can see, order was not maintained when we were looping through that dictionary.
Data one got printed first with a value of 50, but then all of a sudden data three got printed next
with a value of 150.
Then data two with a value of 100 and then data four with a value of 200.
So as you can see with our array, order was maintained but with our dictionary order was not maintained.
Okay.
So let's go ahead and take a look at the next loop here, which is our while loop.
And these loops execute repeatedly until a condition is met.
However, it's very crucial to note that these loops can be dangerous as they have the ability to crash
our game if we do not yield the loop when it continually executes forever.
What do I mean by yielding the loop?
Well, when the main thread of execution hops into the block of code or the scope for that loop and
starts executing, it needs to be able to yield or escape out of the loop at some point in order to
execute other scripts in your game and other crucial engine tasks to keep the game running smoothly.
When you have an infinite loop and it does not yield, it holds the main thread of execution hostage,
and that thread will not be able to execute any other processes in the game engine which will cause
the game to freeze and crash.
The four loops that we took a look at here earlier do not require a yield, and that's because they
are finite, right?
They only execute a finite number of times.
Even if you have a for loop that executes a thousand times, those executions will happen almost instantaneously.
So a yield is not needed.
But if we have a while loop that executes forever, we must yield the main thread of execution to avoid
a crash.
So I'm going to demonstrate to you what happens when we do not yield a while loop.
To create a while loop, we type out the while keyword and after this while keyword, we need to create
a condition to check.
So this could be any condition in your game.
Maybe you want to check if the value of a specific property is equal to another value, or you want
to check if a number is greater than or equal to another number, whatever.
But in this case, I want to create an infinitely executing loop.
So all I'm going to do is just pass the value of true here.
And then we put do again to create a new scope.
And now we have created an infinitely executing loop.
So our interpreter or the main thread of execution is going to start at the top of our script.
It's going to go down through each of these for loops and execute every single one of them.
And then eventually it's going to hit this while loop here, and it's going to hop into this while loop.
And if this while loop does not yield, that thread is going to be stuck in here forever, which is
going to cause our game to crash.
So I'm going to do in this while loop is just print out like high into the console.
And when I hit run you're going to see studio freeze and probably crash.
So let's go ahead and see what happens.
We hit run.
And as you can see already, our game is refusing to load and my mouse is lagging.
And there we go.
Studio has just crashed.
Thankfully, studio has an inbuilt feature where if it detects that the main thread of execution is
stuck in a forever loop, then it will create a script timeout error and it says exhausted allowed execution
time.
So it recognized that our thread got stuck in an infinite loop and eventually stopped the game entirely
and allowed us to go back to our script.
But as you can see, having an infinite loop that does not yield is bad news for our game.
All right, completely bad news.
So now that we know the dangers of using while loops, your next question is probably going to be how
do we yield out of a while loop?
Well, we can do so by using a function in another library called the Task library.
The task library holds several functions to help us manage the yielding and execution of our code.
There's one function in the task library called task Dot.
Wait.
So to access the task library, I simply type out task and then index it.
And here we can see several different functions.
But the one we're going to take a look at here is the wait function.
And here's the description it says yields the current thread until the next heartbeat in which the given
duration in seconds has passed without throttling.
So what this is saying is we pass a number to this function, and this function is going to allow the
thread of execution to exit out of whatever block of code it's in.
And then after that duration is up, it's going to hop back into that block of code it originally left
and continue executing.
So we can autofill this here.
And we can go ahead and pass a number to represent how many seconds we would like to yield for.
So if I put like one here, what's going to happen is the main thread is going to print hi in the console.
And then it's going to encounter this yield function here.
It's going to hop out of this while loop and start executing other important game stuff.
And then once one second has surpassed it hops back into the original point and continues the next cycle
of the while loop.
So it'll print hi again, and then it'll go and yield again and continue doing this on and on and on
for infinity.
Now, if you leave this blank here, what's going to happen is this while loop is going to execute extremely
fast.
And this is because the default time duration for tasks wait is 0.016 seconds, which happens to match
60 frames per second.
This is because Roblox runs at 60 frames per second, and the time duration between each of those frames
is 0.016 seconds.
But for this example, I'm going to put the value of one here.
And then if we hit run, you're going to see inside of our console every single second we're getting
a new high printed out.
So one second goes by get another high another second high high high.
And it's going to continually do this for infinity.
That's the purpose of an infinite while loop.
We have a block of code that we want to execute forever and ever.
Now we can also have our while loop act like a for loop, and it's a little bit more complicated.
But what I'm going to do is I'll create a variable outside of my while loop.
I'm going to call it I, and I'm just going to set it equal to the value of one.
And then what I'm going to do is for my condition here, I'm going to check if I is less than ten.
So as long as I is less than ten, we're going to execute this block of code here for our while loop.
So I'm going to put I here and then to check if it's less than the value of ten.
We use the less than symbol.
And then we can put ten here.
And we're going to do is we are going to increment I by one.
So we're going to set I equal to itself.
And then we're going to use the plus sign and add the value of one to I.
So if I is one that means one plus one is two.
We update the value in here to become two, and it's going to continually loop and do that.
And then once the value of I surpasses ten or it's no longer less than ten, then this while loop is
going to end because the condition has become false.
So what I'm going to do here is I'm going to get rid of this yield statement, but instead I'm going
to print out I into the console.
And then we can go ahead and run our game.
As you can see, I got printed as two and then three and then four, five, six, seven, eight, nine
until it hit ten.
And then once I has reached the value of ten, ten is not less than ten.
So the condition became false and we broke out of that while loop.
So as you can see, this while loop is acting the exact same as a for loop.
It's just a little bit more complicated to do it this way.
So that's why you would want to instead use a for loop.
Okay, so the last loop we're going to take a look at is the repeat loop.
This loop again is very similar to the while loop.
But there is a slight difference.
Before our while loop executes.
Right.
It first checks this condition up here.
If this condition is already false, then this block of code is never going to have the chance to execute.
However, with the repeat loop, instead of the condition being checked first, the condition is actually
checked last.
So that means if the condition is false at the start, it's still guaranteed to execute this loop at
least once.
So you'll see what I mean.
To create a repeat loop, we type out the repeat keyword and then we hit enter.
And then this next keyword gets automatically filled in here.
And this is the until keyword.
And after this until keyword is where we want to pass a condition.
So as an example what I'm going to do is I'm going to set my I variable equal to we'll do zero.
And inside of here we can print out I into the console and then we're going to increment I by one.
So we do I is equal to I plus one.
And then we don't want to continue looping once I becomes greater than ten.
So this is reading out like basic English.
Repeat this block of code until I becomes greater than the value of ten.
So if we go ahead and hit run here.
As you can see, we get ten iterations of our repeat loop.
We print zero, one, two, three all the way to ten.
And then once I has attained the value of 11, that is greater than ten.
So our repeat loop has ended.
Now I want to show you what happens if I is already 11.
Right?
If I is already 11, that means this condition has already evaluated to true and it will break out of
this repeat loop.
But that's not what's going to happen here.
It's because we check this condition at the end.
Meaning this block of code right here is guaranteed to execute at least once.
So that means if we hit run here.
As you can see, we still got it printed out inside of the console value of 11, right?
We printed out 11 here, and then we incremented 11 by one, and then it finally broke out of the repeat
loop.
So actually what I'm going to do is I'm going to move this here.
To be before our print statement.
And then I'm going to run the game again.
And as you can see, the value of 12 got printed out into the console, even though 12 is already greater
than ten, right?
It's because the condition is checked last.
A repeat loop is always guaranteed to execute at least once.
All righty.
And that concludes this lecture on loops in Lua.
I hope you've learned quite a lot and are ready to start putting these loops to use, because you will
be using them a lot in your scripts.
So get comfortable and I will see you in the next lecture.